package com.bqdu.controller;

import com.bqdu.common.Constant;
import com.bqdu.demo1.domain.SeckillCommodity;
import com.bqdu.demo1.service.SeckillCommodityService;
import com.bqdu.demo1.service.SeckillOrderService;
import com.bqdu.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("placeAnOrder")
public class PlaceAnOrderController {

    @Autowired
    private SeckillOrderService seckillOrderService;
    @Autowired
    private SeckillCommodityService seckillCommodityService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 这种写法有问题，查看商品是否有库存这一步，多线程的时候，有可能会导致超卖，因为获取库存量这一步可能数据库已经改变了，但进程读取的时候还没变
     * 所以需要将获取库存量给加个线程锁
     * @param id
     * @return
     */
   /* @PostMapping("{id}")
    public String xiaDan(@PathVariable("id") Integer id){
        //查看商品是否有库存
        SeckillCommodity commodity = seckillCommodityService.getById(id);
        if(commodity.getStock() <= 0){
            System.out.println(commodity.getName()+"没有库存了");
            return commodity.getName()+"没有库存了";
        }
        //生成订单
        try {
            orderService.generateOrder(commodity);
        }catch (Exception e){
            log.error(e.getMessage());
            return commodity.getName()+"没有库存了";
        }
        return commodity.getName()+"下单成功";
    }*/


    /**
     * 这样任然不行，判断是否还有库存，仍然存在超卖的情况
     * @param id
     * @return
     */
   /* @PostMapping("{id}")
    public String xiaDan(@PathVariable("id") Long id){
        //查看商品是否有库存
        Integer stock = Integer.valueOf(redisTemplate.opsForValue().get(Constant.COMMODITY_ID_PREFIX + id).toString());
        SeckillCommodity commodity = seckillCommodityService.getById(id);

        if(stock <= 0){
            System.out.println(commodity.getName()+"没有库存了");
            return commodity.getName()+"没有库存了";
        }

        //生成订单
        try {
            orderService.generateOrder(commodity);
        }catch (Exception e){
            //报了异常，mysql的会事务回滚，但是redis不会，所以redis的数量需要加回去
            redisTemplate.opsForValue().increment(Constant.COMMODITY_ID_PREFIX+id);
            log.error(e.getMessage());
            return commodity.getName()+"没有库存了";
        }
        return commodity.getName()+"下单成功";
    }*/

    /**
     * 这样可以了，因为redis是线程安全的，redis进行读取，更新操作是线程安全的
     * 上一个是读取操作，没有更新库存量，没有触发对数据的锁，所以获取仍然是有问题的
     * @param id
     * @return
     */
    @PostMapping("{id}")
    public String xiaDan(@PathVariable("id") Long id){
        //查看商品是否有库存
        Integer stock = Integer.valueOf(redisTemplate.opsForValue().decrement(Constant.COMMODITY_ID_PREFIX + id).toString());
        SeckillCommodity commodity = seckillCommodityService.getById(id);
        if(stock < 0){
            System.out.println(commodity.getName()+"没有库存了");
            return commodity.getName()+"没有库存了";
        }

        //生成订单
        try {
            orderService.generateOrder(commodity);
        }catch (Exception e){
            //报了异常，mysql的会事务回滚，但是redis不会，所以redis的数量需要加回去
            redisTemplate.opsForValue().increment(Constant.COMMODITY_ID_PREFIX+id);
            log.error(e.getMessage());
            return commodity.getName()+"没有库存了";
        }
        return commodity.getName()+"下单成功";
    }

    @PostMapping("redis")
    public String setRedis(Long id,Integer num){
        redisTemplate.opsForValue().set(Constant.COMMODITY_ID_PREFIX+id,num);
        redisTemplate.opsForValue().decrement(Constant.COMMODITY_ID_PREFIX+id);
        Integer res = Integer.valueOf(redisTemplate.opsForValue().get(Constant.COMMODITY_ID_PREFIX + id).toString());
        System.out.println(res);
        return res.toString();
    }

}
